#include "list.h"
#include <malloc.h>
/*
* 函数功能：创建一个 List 并返回 
* return : 创建的 List
*/
DYMList DYMListCreateList()
{
    DYMList ret = {
        .buffer = NULL,
        .size = 0
    };
    return ret;
}

/*
* 函数功能：在 list 头部添加一个元素
* @param list: 待操作链表
* @param elem: 待插入元素 
* return 操作结果: 1、操作成功返回 1；2、操作失败返回 0 
*/
int DYMListPushFront(DYMList *list, const DYMListDataType elem)
{
    int ret = 0;
    //  在下面填写你的代码
    if(list == NULL) return 0;

    /* 1、若链表为空，插入操作单独处理 */
    if(list->size == 0 || list->buffer == NULL)
    {
        struct _list_node *tmp = (struct _list_node*) malloc(sizeof(struct _list_node));
        if(tmp == NULL) return 0;
        tmp->next = tmp;
        tmp->prev = tmp;
        tmp->data = elem;

        list->buffer = tmp;
        list->size = 1;
        ret = 1;
    
    /* 2、链表不为空，插入操作如下 */
    }else{
        struct _list_node *tmp = (struct _list_node*) malloc(sizeof(struct _list_node));
        if(tmp == NULL) return 0;
        tmp->data = elem;
        tmp->next = list->buffer;           // 新的首节点的后指针指向旧的首节点
        tmp->prev = list->buffer->prev;     // 新的首节点的前指针指向尾元素
        list->buffer->prev->next = tmp;     // 尾元素的后指针指向新的首节点
        list->buffer->prev = tmp;           // 旧的首节点的前指针指向新的首节点
        list->buffer = tmp;                 // 更新新的首节点
        list->size++;
        ret = 1;
    }
    return ret;
}

/*
* 函数功能：在 list 尾部添加一个元素
* @param list: 待操作链表
* @param elem: 待插入元素 
* return 操作结果: 1、操作成功返回 1；2、操作失败返回 0
*/
int DYMListPushBack(DYMList *list, const DYMListDataType elem)
{ 
    int ret = 0;
    //  在下面填写你的代码
    if(list == NULL) return 0;

    /* 1、若链表为空，插入操作单独处理 */
    if(list->size == 0 || list->buffer == NULL)
    {
        struct _list_node *tmp = (struct _list_node*) malloc(sizeof(struct _list_node));
        if(tmp == NULL) return 0;
        tmp->next = tmp;
        tmp->prev = tmp;
        tmp->data = elem;

        list->buffer = tmp;
        list->size = 1;
        ret = 1;
    
    /* 2、链表不为空，插入操作如下 */
    }else{
        struct _list_node *tmp = (struct _list_node*) malloc(sizeof(struct _list_node));
        if(tmp == NULL) return 0;
        tmp->data = elem;
        tmp->next = list->buffer;           // 新的尾节点的后指针指向首节点
        tmp->prev = list->buffer->prev;     // 新的尾节点的前指针指向尾元素
        list->buffer->prev->next = tmp;     // 尾元素的后指针指向新的尾节点
        list->buffer->prev = tmp;           // 首节点的前指针指向新的尾节点
        list->size++;
        ret = 1;
    }
    return ret;
}

/*
* 函数功能：在 list 头部删除一个元素
* @param list: 待操作链表
* @param buffer: 若 buffer 不为 NULL,则被删除元素的值将被写入 buffer;
* return 操作结果: 1、操作成功返回 1；2、操作失败返回 0
*/
int DYMListPopFront(DYMList *list, DYMListDataType *buffer)
{
    int ret = 0;
    //  在下面填写你的代码
    if(list == NULL) return 0;
    if(list->size == 0 || list->buffer == NULL) return 0;
    
    // 向外面传出第一个元素
    if(buffer != NULL){
        *buffer = list->buffer->data;
    }

    /* 链表中只有一个元素 */
    if(list->size == 1){
        free(list->buffer);
        list->buffer = NULL;
        list->size = 0;
        ret = 1;
    }else{
        struct _list_node *tmp = list->buffer;
        list->buffer = tmp->next;
        tmp->prev->next = list->buffer;
        list->buffer->prev = tmp->prev;
        free(tmp);
        list->size--;
        ret = 1;
    }
    
    return ret;
}

/*
* 函数功能：在 list 尾部删除一个元素
* @param list: 待操作链表
* @param buffer: 若 buffer 不为 NULL,则被删除元素的值将被写入 buffer;
* return 操作结果: 1、操作成功返回 1；2、操作失败返回 0
*/
int DYMListPopBack(DYMList *list, DYMListDataType *buffer)
{
    int ret = 0;
    //  在下面填写你的代码
    if(list == NULL) return 0;
    if(list->size == 0 || list->buffer == NULL) return 0;
    
    // 向外面传出最后一个元素
    if(buffer != NULL){
        *buffer = list->buffer->prev->data;
    }

    /* 链表中只有一个元素 */
    if(list->size == 1){
        free(list->buffer);
        list->buffer = NULL;
        list->size = 0;
        ret = 1;
    }else{
        struct _list_node *tmp = list->buffer->prev;
        list->buffer->prev = tmp->prev;
        tmp->prev->next = list->buffer;
        free(tmp);
        list->size--;
        ret = 1;
    }
    
    return ret;
}

/*
* 函数功能：从 list 中删除所有值为 elem 的元素, 并返回操作结果
* @param list: 待操作链表
* @param elem: 待删除元素
* @param equal: 比较两个 elem 是否相等的函数指针，该函数指针挂载的函数应当满足 1、a == b 返回 1；
                                                                          2、a != b 返回 0；
* return 操作结果: 1、操作成功返回 1；2、操作失败返回 0
*/
int DYMListDelete(DYMList *list,const DYMListDataType elem, int (*equal)(const DYMListDataType *a,const DYMListDataType *b))
{
    int ret = 0;
    //  在下面填写你的代码
    if(list == NULL || equal == NULL) return 0;
    if(list->size == 0 || list->buffer == NULL) return 0;
    
    /* 处理只有一个元素的情况 */
    if(list->size == 1)
    {
        if(1 == equal(&list->buffer->data, &elem)){
            list->size = 0;
            free(list->buffer);
            list->buffer = NULL;
            ret = 1;
        }else{
            return 0;
        }

    /* 处理不止一个元素的情况 */
    }else
    {
        /* 先不处理第一个元素 */
        struct _list_node* tmp = list->buffer->next;
        while (tmp != list->buffer)
        {
            if(1 == equal(&tmp->data, &elem))
            {
                struct _list_node* waitToFree = tmp;
                tmp = tmp->next;
                tmp->prev = waitToFree->prev;
                waitToFree->prev->next = tmp;
                free(waitToFree);
                list->size--;
                ret = 1;
            }else{
                tmp = tmp->next;
            }
        }
        
        /* 处理第一个元素 */
        if(equal(&list->buffer->data, &elem) == 1)
        {
            DYMListPopFront(list, NULL);
            ret = 1;
        }
    }
    return ret;
}

/*
* 函数功能：判断 list 中是否包含值为 elem 的元素，若包含返回 1， 否则返回 0。
* @param list: 待操作链表
* @param elem: 待查找的元素
* @param equal: 比较两个 elem 是否相等的函数指针，该函数指针挂载的函数应当满足 1、a == b 返回 1；
                                                                          2、a != b 返回 0；
* return 操作结果: 1、操作成功返回 1；2、操作失败返回 0
*/
int DYMListContain(DYMList *list,const DYMListDataType elem, int (*equal)(const DYMListDataType *a, const DYMListDataType *b))
{
    int ret = 0;
    //  在下面填写你的代码
    if(list == NULL || equal == NULL) return 0;
    if(list->size == 0 || list->buffer == NULL) return 0;

    struct _list_node* tmp = list->buffer;
    for(int i = 0; i < list->size; ++i)
    {
        if(equal(&tmp->data, &elem) == 1){
            ret = 1;
            break;
        }else{
            tmp = tmp->next;
        }
    }
    
    return ret;
}

/*
* 函数功能：销毁一个链表 list
* @param list: 待操作链表
*/
void DYMListDestoty(DYMList *list)
{
    //  在下面填写你的代码
    if(list == NULL) return;
    if(list->size == 0 && list->buffer == NULL) return;
    struct _list_node *tmp;
    for(int i = 0; i < list->size; ++i){
        tmp = list->buffer;
        list->buffer = list->buffer->next;
        free(tmp);
    }
    list->buffer = NULL;
    list->size = 0;
}

void DYMListForeach(DYMList *list, void (*visit)(DYMListDataType* data))
{
    if(!list) return;
    struct _list_node *tmp = list->buffer;
    
    for(int i = 0; i < list->size; ++i)
    {
        visit(&tmp->data);
        tmp = tmp->next;
    }
}
void DYMListReverseForeach(DYMList *list, void (*visit)(DYMListDataType* data))
{
    if(!list) return;
    struct _list_node *tmp = list->buffer->prev;
    
    for(int i = 0; i < list->size; ++i)
    {
        visit(&tmp->data);
        tmp = tmp->prev;
    }
}